#if !defined(___BMP_C)
#define ___BMP_C
#include "std.h"


#if !defined(___SYS_I386)
#error Invalid system
#endif


I4 BmpRead1(tBmp *bmp,FILE *f1,N1 xd,N1 yd)
{ N4 i1,i2,ii,nn=0;
  N1 *s,c1; N2 n2; N4 n4;
  N4 xl,yl,flen,offs;
  if (!bmp)
    ERR1("Error: BmpRead1: Param",0ul);
  bmp->f1=f1; bmp->pp=NULL;
  if (!f1)
    ERR1("Error: BmpRead1: Param",0ul);

  // Init (file)
  READ1(&c1,1,f1);
  if (ii!=1 || c1!='B')
    ERR1("Error: BMP: Init/1 (B)",nn);
  READ1(&c1,1,f1);
  if (ii!=1 || c1!='M')
    ERR1("Error: BMP: Init/2 (M)",nn);
  // ..4:FileLen (14+40+pal*4+bmp)
  READ1(&n4,4,f1); flen=n4;
  if (ii!=1)
    ERR1("Error: BMP: FileLen",nn);
  // ..4:AppData
  READ1(&n4,4,f1);
  if (ii!=1)
    ERR1("Error: BMP: AppData",nn);
  // ..4:BmpOffs (14+40+pal*4)
  READ1(&n4,4,f1); offs=n4;
  if (ii!=1)
    ERR1("Error: BMP: BmpOffs",nn);
  // Init (bmp)
  // ..4:InfoLen
  READ1(&n4,4,f1);
  if (ii!=1 || n4!=40)
    ERR1("Error: BMP: InfoLen",nn);
  // ..4:XLen
  READ1(&n4,4,f1); xl=n4;
  if (ii!=1 || n4>0xFFFFul)
    ERR1("Error: BMP: XLen",nn);
  bmp->xl2=(xl*3+3)/4*4;
  // ..4:YLen
  READ1(&n4,4,f1); yl=n4;
  if (ii!=1 || n4>0xFFFFul)
    ERR1("Error: BMP: YLen",nn);
  // ..2:Type(disp,prn,...) 
  READ1(&n2,2,f1);
  if (ii!=1 || n2!=1)
    ERR1("Error: BMP: Type",nn);
  // ..2:Depth
  READ1(&n2,2,f1);
  if (ii!=1 || n2!=24)
    ERR1("Error: BMP: Depth",nn);
  // ..4:Compression
  READ1(&n4,4,f1);
  if (ii!=1 || n4!=0)
    ERR1("Error: BMP: Compression",nn);
  // ..4:BmpLen
  READ1(&n4,4,f1);
  if (ii!=1)
    ERR1("Error: BMP: BmpLen",nn);
  // ..4:XDens
  READ1(&n4,4,f1);
  if (ii!=1)
    ERR1("Error: BMP: XDens",nn);
  // ..4:YDens
  READ1(&n4,4,f1);
  if (ii!=1)
    ERR1("Error: BMP: YDens",nn);
  // ..4:PalNum
  READ1(&n4,4,f1);
  if (ii!=1 || n4!=0)
    ERR1("Error: BMP: PalNum",nn);
  // ..4:PalUsed
  READ1(&n4,4,f1);
  if (ii!=1 || n4!=0)
    ERR1("Error: BMP: PalUsed",nn);
  if (offs!=14+40)
    ERR1("Error: BMP: Invalid BmpOffs",nn);
  if (flen!=offs+yl*bmp->xl2)
    ERR1("Error: BMP: Invalid FileLen",nn);
  bmp->xm=(xl+xd-1)/xd*xd;
  bmp->ym=(yl+yd-1)/yd*yd;
  bmp->xm2=(bmp->xm*3+3)/4*4;

  if (!(bmp->pp=MemGet(bmp->ym*bmp->xm2)))
    ERR1("Error: BmpRead: Nomem",nn);
  bmp->xl=xl; bmp->yl=yl;
  s=bmp->pp+bmp->yl*bmp->xm2;
  for (i1=0;i1<bmp->yl;++i1)
  { s-=bmp->xm2;
    READ1(s,bmp->xl2,f1);
    if (ii!=1)
      ERR1("Error: BmpRead: Read",nn);
  }
  for (s=bmp->pp,i1=0;i1<bmp->yl;++i1)
    for (s+=bmp->xl2,i2=bmp->xl2;i2<bmp->xm2;++i2)
      *(s++)=0;
  s=bmp->pp+bmp->yl*bmp->xm2;
  for (i1=bmp->yl;i1<bmp->ym;++i1)
    for (i2=0;i2<bmp->xm2;++i2)
      *(s++)=0;

  return (0);
}

I4 BmpRead2(tBmp *bmp)
{ if (!bmp || !bmp->pp)
    ERR1("Error: BmpRead2: Param",0ul);
  MemRel(bmp->pp); bmp->pp=NULL;
  return (0);
}

I4 BmpWrite1(tBmp *bmp,FILE *f1,
  N4 xm,N4 ym,N4 xl,N4 yl)
{ N4 n; Str s;
  if (!bmp)
    ERR1("Error: BmpWrite1: Param",0ul);
  bmp->f1=f1; bmp->pp=NULL;
  if (!f1) return (0);
  if (xm<xl) xm=xl;
  if (ym<yl) ym=yl;
  bmp->xm=xm; bmp->ym=ym;
  bmp->xl=xl; bmp->yl=yl;
  bmp->xm2=(xm*3+3)/4*4;
  bmp->xl2=(xl*3+3)/4*4;
  if (!(s=bmp->pp=
    MemGet(n=ym*bmp->xm2)))
    ERR1("Error: BmpBeg: Nomem",0ul);
  while (n--) *(s++)=0;

  // Init (file)
  fputc('B',f1);
  fputc('M',f1);
  // ..4:FileLen
  n=14+40+yl*bmp->xl2;
  fwrite(&n,4,1,f1);
  // ..4:AppData
  n=0;
  fwrite(&n,4,1,f1);
  // ..4:BmpOffs
  n=14+40;
  fwrite(&n,4,1,f1);
  // Init (bmp)
  // ..4:InfoLen
  n=40;
  fwrite(&n,4,1,f1);
  // ..4:XLen
  n=xl;
  fwrite(&n,4,1,f1);
  // ..4:YLen
  n=yl;
  fwrite(&n,4,1,f1);
  // ..2:Type(disp,prn,...)
  n=1;
  fwrite(&n,2,1,f1);
  // ..2:Depth
  n=24;
  fwrite(&n,2,1,f1);
  // ..4:Compression
  n=0;
  fwrite(&n,4,1,f1);
  // ..4:BmpLen
  n=0;
  fwrite(&n,4,1,f1);
  // ..4:XDens (dpm)
  n=0;
  fwrite(&n,4,1,f1);
  // ..4:YDens (dpm)
  n=0;
  fwrite(&n,4,1,f1);
  // ..4:PalNum
  n=0;
  fwrite(&n,4,1,f1);
  // ..4:PalUsed
  n=0;
  fwrite(&n,4,1,f1);

  fflush(f1);
  return (0);
}

I4 BmpWrite2(tBmp *bmp)
{ N4 i1,i2; Str s1;
  if (!bmp || !bmp->pp)
    ERR1("Error: BmpWrite2: Param",0ul);
  if (!bmp->f1) return (0);
  s1=bmp->pp;
  for (i1=0;i1<bmp->yl;++i1)
  { i2=bmp->xl*3; s1+=i2;
    for (;i2<bmp->xl2;++i2)
      *(s1++)=0;
    s1+=bmp->xm2-bmp->xl2;
  }
  s1=bmp->pp+bmp->yl*bmp->xm2;
  for (i1=0;i1<bmp->yl;++i1)
  { s1-=bmp->xm2;
    fwrite(s1,bmp->xl2,1,bmp->f1);
  }
  MemRel(bmp->pp);
  bmp->pp=NULL;
  return (0);
}

I4 BmpGet(tBmp *bmp,N4 x,N4 y,
  N1 *cr,N1 *cg,N1 *cb)
{ Str s;
  if (!bmp) return (-1l);
  if (!bmp->pp) return (-1l);
  s=bmp->pp+y*bmp->xm2+x*3;
  if (cb) *cb=*(s++);
  if (cg) *cg=*(s++);
  if (cr) *cr=*(s++);
  return (0);
}

I4 BmpSet(tBmp *bmp,N4 x,N4 y,
  N1 cr,N1 cg,N1 cb)
{ Str s;
  if (!bmp) return (-1l);
  if (!bmp->f1) return (0);
  if (!bmp->pp) return (-1l);
  s=bmp->pp+y*bmp->xm2+x*3;
  *(s++)=cb; *(s++)=cg; *(s++)=cr;
  return (0);
}


#endif
